package cn.peach.hrm.userdetail;

import cn.peach.hrm.domain.Login;
import cn.peach.hrm.domain.Permission;
import cn.peach.hrm.mapper.PermissionMapper;
import cn.peach.hrm.service.ILoginService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用来提供给security的用户信息的service，
 * 我们需要复写 loadUserByUsername 方法返回数据库中的用户信息
 */
@Slf4j
@Component
public class MyUserDetailService implements UserDetailsService {

    @Autowired
    private ILoginService loginService;

    @Autowired
    private PermissionMapper permissionMapper;

    /**
     * 加载数据库中的认证的用户的信息：用户名，密码，用户的权限列表
     * @param username: 该方法把username传入进来，我们通过username查询用户的信息
     * (密码，权限列表等)然后封装成 UserDetails进行返回 ，交给security 。
     */
    @Override
    public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException {
        EntityWrapper<Login> wrapper = new EntityWrapper<>();
        wrapper.eq("username", username);
        // 查出用户名
        Login loginName = loginService.selectOne(wrapper);
        if (loginName == null) {
            throw new UsernameNotFoundException("无效的用户名");
        }
        // 查询用户权限
        List<GrantedAuthority> authPermission = new ArrayList<>();
        List<Permission> permissions = permissionMapper.selectPermissionsByUserId(loginName.getId());
        if (!permissions.isEmpty()) {
            authPermission = permissions.stream().map( p -> new SimpleGrantedAuthority(p.getSn())).collect(Collectors.toList());
        }
        log.info("加载用户的权限 {}", authPermission);
        Map<String, Object> map = new HashMap<>();
        map.put("id", loginName.getId());
        map.put("username", loginName.getUsername());
        map.put("tennatId", loginName.getTenantId());
        map.put("tennatName", loginName.getTenantName());
        //密码是基于BCryptPasswordEncoder加密的密文
        //User是security内部的对象，UserDetails的实现类
        //用来封装用户的基本信息(用户名，密码，权限列表)
        return new User(JSON.toJSONString(map), loginName.getPassword(), loginName.getEnabled(), loginName.getAccountNonExpired(), loginName.getCredentialsNonExpired(), loginName.getAccountNonLocked(), authPermission);
    }
}

